package com.kexilo.core.common.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.regex.Pattern;

/**
 * 安全工具类
 * 提供XSS防护、输入验证等安全功能
 * 
 * @author Kexilo
 */
@Component
public class SecurityUtils {
    
    private static final Logger log = LoggerFactory.getLogger(SecurityUtils.class);
    
    // XSS攻击模式
    private static final Pattern[] XSS_PATTERNS = {
        Pattern.compile("<script[^>]*>.*?</script>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL),
        Pattern.compile("<script[^>]*>", Pattern.CASE_INSENSITIVE),
        Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
        Pattern.compile("on\\w+\\s*=", Pattern.CASE_INSENSITIVE),
        Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
        Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
        Pattern.compile("data:text/html", Pattern.CASE_INSENSITIVE),
        Pattern.compile("<iframe[^>]*>.*?</iframe>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL),
        Pattern.compile("<object[^>]*>.*?</object>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL),
        Pattern.compile("<embed[^>]*>.*?</embed>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL),
        Pattern.compile("expression\\s*\\(", Pattern.CASE_INSENSITIVE)
    };
    
    /**
     * XSS防护 - 清理恶意脚本
     * 
     * @param input 输入字符串
     * @return 清理后的字符串
     */
    public static String cleanXss(String input) {
        if (input == null || input.trim().isEmpty()) {
            return input;
        }
        
        String cleanInput = input;
        
        // 应用XSS清理模式
        for (Pattern pattern : XSS_PATTERNS) {
            cleanInput = pattern.matcher(cleanInput).replaceAll("");
        }
        
        // HTML实体编码
        cleanInput = htmlEncode(cleanInput);
        
        return cleanInput;
    }
    
    /**
     * HTML实体编码
     * 
     * @param input 输入字符串
     * @return 编码后的字符串
     */
    public static String htmlEncode(String input) {
        if (input == null) {
            return null;
        }
        
        return input
                .replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&#x27;")
                .replace("/", "&#x2F;");
    }
    
    /**
     * SQL注入防护 - 检查危险字符
     * 
     * @param input 输入字符串
     * @return 是否包含SQL注入风险
     */
    public static boolean containsSqlInjection(String input) {
        if (input == null || input.trim().isEmpty()) {
            return false;
        }
        
        String lowerInput = input.toLowerCase();
        
        // SQL注入关键词
        String[] sqlKeywords = {
            "select", "insert", "update", "delete", "drop", "create", "alter",
            "exec", "execute", "union", "script", "declare", "cast", "convert",
            "or 1=1", "and 1=1", "' or '1'='1", "\" or \"1\"=\"1",
            "--", "/*", "*/", "xp_", "sp_", "@@"
        };
        
        for (String keyword : sqlKeywords) {
            if (lowerInput.contains(keyword)) {
                log.warn("检测到潜在SQL注入: {}", input);
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 路径遍历攻击防护
     * 
     * @param path 文件路径
     * @return 是否安全
     */
    public static boolean isPathSafe(String path) {
        if (path == null || path.trim().isEmpty()) {
            return false;
        }
        
        // 检查路径遍历攻击
        return !path.contains("../") && 
               !path.contains("..\\") && 
               !path.contains("./") &&
               !path.contains(".\\") &&
               !path.startsWith("/") &&
               !path.contains(":");
    }
    
    /**
     * 验证邮箱格式
     * 
     * @param email 邮箱地址
     * @return 是否有效
     */
    public static boolean isValidEmail(String email) {
        if (email == null || email.trim().isEmpty()) {
            return false;
        }
        
        String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
        return email.matches(emailRegex);
    }
    
    /**
     * 验证手机号格式
     * 
     * @param phone 手机号
     * @return 是否有效
     */
    public static boolean isValidPhone(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
        
        String phoneRegex = "^1[3-9]\\d{9}$";
        return phone.matches(phoneRegex);
    }
    
    /**
     * 验证密码强度
     * 
     * @param password 密码
     * @return 强度等级 (0-4)
     */
    public static int getPasswordStrength(String password) {
        if (password == null || password.length() < 6) {
            return 0;
        }
        
        int strength = 0;
        
        // 长度检查
        if (password.length() >= 8) strength++;
        if (password.length() >= 12) strength++;
        
        // 字符类型检查
        if (password.matches(".*[a-z].*")) strength++; // 小写字母
        if (password.matches(".*[A-Z].*")) strength++; // 大写字母
        if (password.matches(".*[0-9].*")) strength++; // 数字
        if (password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?].*")) strength++; // 特殊字符
        
        return Math.min(strength, 4);
    }
    
    /**
     * 生成安全的随机字符串
     * 
     * @param length 长度
     * @return 随机字符串
     */
    public static String generateSecureRandomString(int length) {
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        java.security.SecureRandom random = new java.security.SecureRandom();
        StringBuilder sb = new StringBuilder();
        
        for (int i = 0; i < length; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        
        return sb.toString();
    }
    
    /**
     * IP地址验证
     * 
     * @param ip IP地址
     * @return 是否有效
     */
    public static boolean isValidIpAddress(String ip) {
        if (ip == null || ip.trim().isEmpty()) {
            return false;
        }
        
        String ipRegex = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
        return ip.matches(ipRegex);
    }
    
    /**
     * 检查是否为私有IP地址
     * 
     * @param ip IP地址
     * @return 是否为私有IP
     */
    public static boolean isPrivateIpAddress(String ip) {
        if (!isValidIpAddress(ip)) {
            return false;
        }
        
        String[] parts = ip.split("\\.");
        int firstOctet = Integer.parseInt(parts[0]);
        int secondOctet = Integer.parseInt(parts[1]);
        
        // 10.0.0.0/8
        if (firstOctet == 10) {
            return true;
        }
        
        // 172.16.0.0/12
        if (firstOctet == 172 && secondOctet >= 16 && secondOctet <= 31) {
            return true;
        }
        
        // 192.168.0.0/16
        if (firstOctet == 192 && secondOctet == 168) {
            return true;
        }
        
        // 127.0.0.0/8 (localhost)
        if (firstOctet == 127) {
            return true;
        }
        
        return false;
    }
    
    /**
     * 生成CSRF Token
     * 
     * @return CSRF Token
     */
    public static String generateCsrfToken() {
        return java.util.UUID.randomUUID().toString().replace("-", "");
    }
    
    /**
     * 验证CSRF Token
     * 
     * @param sessionToken 会话中的Token
     * @param requestToken 请求中的Token
     * @return 是否有效
     */
    public static boolean validateCsrfToken(String sessionToken, String requestToken) {
        if (sessionToken == null || requestToken == null) {
            return false;
        }
        
        return sessionToken.equals(requestToken);
    }
    
    /**
     * 安全比较字符串（防止时序攻击）
     * 
     * @param a 字符串A
     * @param b 字符串B
     * @return 是否相等
     */
    public static boolean secureEquals(String a, String b) {
        if (a == null || b == null) {
            return a == b;
        }
        
        if (a.length() != b.length()) {
            return false;
        }
        
        int result = 0;
        for (int i = 0; i < a.length(); i++) {
            result |= a.charAt(i) ^ b.charAt(i);
        }
        
        return result == 0;
    }
}
